package com.mccken.rapid.core.context;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

import io.netty.channel.ChannelHandlerContext;

/**
 * 基础上下文实现类
 * 
 * @program: rapid_gateway
 * @description:
 * @author: mccken
 * @create: 2022-01-28 14:44
 **/
public abstract class BasicContext implements Context{
	
	protected final String protocol;
	
	protected final ChannelHandlerContext nettyCtx;
	
	protected final boolean keepAlive;
	
	// 上下文的状态标识 
	protected volatile int status = Context.RUNNING;
	
	// 保存所有的上下文参数集合
	protected final Map<AttributeKey<?>, Object> attributes = new HashMap<>();
	
	// 在请求过程中，出现异常则设置异常对象
	protected Throwable throwable;
	
	// 定义一个变量用来标识是否已经释放请求资源
	protected final AtomicBoolean requestReleased = new AtomicBoolean(false);
	
	// 存放回调函数的集合
	protected List<Consumer<Context>> completedCallBacks;
	
	public BasicContext(String protocol, ChannelHandlerContext nettyCtx, boolean keepAlive) {
		this.protocol = protocol;
		this.nettyCtx = nettyCtx;
		this.keepAlive = keepAlive;
	}

	@Override 
	public String getProtocol() {
		return this.protocol;
	}

	// 获取netty的上下文
	@Override
	public ChannelHandlerContext getNettyCtx(){
		return this.nettyCtx;
	}

	// 是否保持连接
	@Override
	public boolean isKeepALive(){
		return this.keepAlive;
	}
	
	/*********************************** 设置网关的状态系 ***********************************************/

	@Override
	public boolean isRunning(){
		return status == Context.RUNNING;
	}

	@Override
	public boolean isWrittended(){
		return status == Context.WRITTEN;
	}

	@Override
	public boolean isCompleted(){
		return status == Context.COMPLETED;
	}

	@Override
	public boolean isTerminated(){
		return status == Context.TERMINATED;
	}

	/*********************************** 判断网关的状态系 ***********************************************/
	
	// 设置上下文状态为正常运行状态
	@Override
	public void runned(){
		status = Context.RUNNING;
	}

	// 设置上下文状态为标记写回
	@Override
	public void writtened(){
		status = Context.WRITTEN;
	}

	// 设置上下文状态为写回完成
	@Override
	public void completed(){
		status = Context.COMPLETED;
	}

	// 设置上下文状态为最终结束
	@Override
	public void terminated(){
		status = Context.TERMINATED;
	}

	// 定义 上下文AttributeKey对象
	// 获取上下文参数
	@Override
	public <T> T getAttribute(AttributeKey<T> key){
		return (T) attributes.get(key);
	}

	@Override
	public <T> T putAttribute(AttributeKey<T> key, T value){
		return (T) attributes.put(key, value);
	}

	@Override
	public void setThrowable(Throwable throwable){
		this.throwable = throwable;
	}

	@Override
	public Throwable getThrowable(){
		return this.throwable;
	}

	// 标记资源是否释放
	@Override
	public void releaseRequest(){
		this.requestReleased.compareAndSet(false, true);
	}

	@Override
	public void completedCallback(Consumer<Context> consumer) {
		if (completedCallBacks == null) {
			completedCallBacks = new ArrayList<>();
		}
		completedCallBacks.add(consumer);
	}

	@Override
	public void invokeCompletedCallback() {
		if (completedCallBacks != null) {
			completedCallBacks.forEach(call -> call.accept(this));
		}
	}
}
